package math;

public class vec3i
{
    
    public static final vec3i ZERO = new vec3i();
    public static final vec3i ONE = new vec3i(1);
    
    
    public int x;
    
    public int y;
    
    public int z;
    
    
    public vec3i()
    {
        this.set(0, 0, 0);
    }
    
    public vec3i(int aXYZ)
    {
        this.set(aXYZ);
    }
    
    public vec3i(
            int aX, 
            int aY, 
            int aZ)
    {
        this.set(aX, aY, aZ);
    }
    
    public vec3i(vec3 aOther)
    {
        this.set(aOther);
    }
    
    
    public final void set(
            int aX, 
            int aY, 
            int aZ)
    {
        this.x = aX;
        this.y = aY;
        this.z = aZ;
    }
    
    public final void set(int aXYZ)
    {
        this.set(aXYZ, aXYZ, aXYZ);
    }
    
    public final void set(vec3i aOther)
    {
        this.set(aOther.x, aOther.y, aOther.z);
    }
    
    public final void set(vec3 aOther)
    {
        this.set((int) aOther.x, (int) aOther.y, (int) aOther.z);
    }
    
    
    public void add(vec3i aTransl)
    {
        this.x += aTransl.x;
        this.y += aTransl.y;
        this.z += aTransl.z;
    }
    
    public void add(int aTransl)
    {
        this.x += aTransl;
        this.y += aTransl;
        this.z += aTransl;
    }
    
    public void sub(vec3i aTransl)
    {
        this.x -= aTransl.x;
        this.y -= aTransl.y;
        this.z -= aTransl.z;
    }
    
    public void sub(int aTransl)
    {
        this.x -= aTransl;
        this.y -= aTransl;
        this.z -= aTransl;
    }
    
    public void mul(vec3i aScale)
    {
        this.x *= aScale.x;
        this.y *= aScale.y;
        this.z *= aScale.z;
    }
    
    public void mul(int aScale)
    {
        this.x *= aScale;
        this.y *= aScale;
        this.z *= aScale;
    }
    
    public void div(vec3i aScale)
    {
        this.x /= aScale.x;
        this.y /= aScale.y;
        this.z /= aScale.z;
    }
    
    public void div(int aScale)
    {
        this.x /= aScale;
        this.y /= aScale;
        this.z /= aScale;
    }
    
    public void pow(vec3i aExp)
    {
        this.x = math.powi(this.x, aExp.x);
        this.y = math.powi(this.y, aExp.y);
        this.z = math.powi(this.z, aExp.z);
    }
    
    public void pow(int aExp)
    {
        this.x = math.powi(this.x, aExp);
        this.y = math.powi(this.y, aExp);
        this.z = math.powi(this.z, aExp);
    }
    
    public void abs()
    {
        this.x = math.absi(this.x);
        this.y = math.absi(this.y);
        this.z = math.absi(this.z);
    }
    
    public void clamp(vec3i aBoundsLo, vec3i aBoundsHi)
    {
        this.x = math.clampi(this.x, aBoundsLo.x, aBoundsHi.x);
        this.y = math.clampi(this.y, aBoundsLo.y, aBoundsHi.y);
        this.z = math.clampi(this.z, aBoundsLo.z, aBoundsHi.z);
    }
    
    public void clamp(int aBoundsLo, int aBoundsHi)
    {
        this.x = math.clampi(this.x, aBoundsLo, aBoundsHi);
        this.y = math.clampi(this.y, aBoundsLo, aBoundsHi);
        this.z = math.clampi(this.z, aBoundsLo, aBoundsHi);
    }
    
    
    public boolean close(vec3i aOther, int aError)
    {
        return (
            math.abs(this.x - aOther.x) < aError && 
            math.abs(this.y - aOther.y) < aError && 
            math.abs(this.z - aOther.z) < aError
        );
    }
    
    public boolean lessAll(vec3i aOther)
    {
        return (
            this.x < aOther.x && 
            this.y < aOther.y && 
            this.z < aOther.z
        );
    }
    
    public boolean lessAny(vec3i aOther)
    {
        return (
            this.x < aOther.x || 
            this.y < aOther.y || 
            this.z < aOther.z
        );
    }
    
    public boolean lequalAll(vec3i aOther)
    {
        return (
            this.x <= aOther.x && 
            this.y <= aOther.y && 
            this.z <= aOther.z
        );
    }
    
    public boolean lequalAny(vec3i aOther)
    {
        return (
            this.x <= aOther.x || 
            this.y <= aOther.y || 
            this.z <= aOther.z
        );
    }
    
    public boolean greaterAll(vec3i aOther)
    {
        return (
            this.x > aOther.x && 
            this.y > aOther.y && 
            this.z > aOther.z
        );
    }
    
    public boolean greaterAny(vec3i aOther)
    {
        return (
            this.x > aOther.x || 
            this.y > aOther.y || 
            this.z > aOther.z
        );
    }
    
    public boolean gequalAll(vec3i aOther)
    {
        return (
            this.x >= aOther.x && 
            this.y >= aOther.y && 
            this.z >= aOther.z
        );
    }
    
    public boolean gequalAny(vec3i aOther)
    {
        return (
            this.x >= aOther.x || 
            this.y >= aOther.y || 
            this.z >= aOther.z
        );
    }
    
    
    public int dot(vec3i aOther)
    {
        return (
            this.x * aOther.x + 
            this.y * aOther.y + 
            this.z * aOther.z
        );
    }
    
    
    public vec3i copy()
    {
        vec3i copy = new vec3i();
        copy.set(this);
        return copy;
    }
    
    
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        sb.append("( ");
        sb.append(this.x);
        sb.append(", ");
        sb.append(this.y);
        sb.append(", ");
        sb.append(this.z);
        sb.append(" )");
        return sb.toString();
    }
    
    
    
    public static vec3i add(vec3i aA, vec3i aB)
    {
        vec3i add = aA.copy();
        add.add(aB);
        return add;
    }
    
    public static vec3i add(vec3i aA, int aB)
    {
        vec3i add = aA.copy();
        add.add(aB);
        return add;
    }
    
    public static vec3i add(int aA, vec3i aB)
    {
        vec3i add = new vec3i(aA);
        add.add(aB);
        return add;
    }
    
    public static vec3i add(int aA, int aB)
    {
        int add = aA + aB;
        return new vec3i(add);
    }
    
    public static vec3i sub(vec3i aA, vec3i aB)
    {
        vec3i sub = aA.copy();
        sub.sub(aB);
        return sub;
    }
    
    public static vec3i sub(vec3i aA, int aB)
    {
        vec3i sub = aA.copy();
        sub.sub(aB);
        return sub;
    }
    
    public static vec3i sub(int aA, vec3i aB)
    {
        vec3i sub = new vec3i(aA);
        sub.sub(aB);
        return sub;
    }
    
    public static vec3i sub(int aA, int aB)
    {
        int sub = aA - aB;
        return new vec3i(sub);
    }
    
    public static vec3i mul(vec3i aA, vec3i aB)
    {
        vec3i mul = aA.copy();
        mul.mul(aB);
        return mul;
    }
    
    public static vec3i mul(vec3i aA, int aB)
    {
        vec3i mul = aA.copy();
        mul.mul(aB);
        return mul;
    }
    
    public static vec3i mul(int aA, vec3i aB)
    {
        vec3i mul = new vec3i(aA);
        mul.mul(aB);
        return mul;
    }
    
    public static vec3i mul(int aA, int aB)
    {
        int mul = aA * aB;
        return new vec3i(mul);
    }
    
    public static vec3i div(vec3i aA, vec3i aB)
    {
        vec3i div = aA.copy();
        div.div(aB);
        return div;
    }
    
    public static vec3i div(vec3i aA, int aB)
    {
        vec3i div = aA.copy();
        div.div(aB);
        return div;
    }
    
    public static vec3i div(int aA, vec3i aB)
    {
        vec3i div = new vec3i(aA);
        div.div(aB);
        return div;
    }
    
    public static vec3i div(int aA, int aB)
    {
        int div = aA / aB;
        return new vec3i(div);
    }
    
    public static vec3i pow(vec3i aVec, vec3i aExp)
    {
        vec3i pow = aVec.copy();
        pow.pow(aExp);
        return pow;
    }
    
    public static vec3i pow(vec3i aVec, int aExp)
    {
        vec3i pow = aVec.copy();
        pow.pow(aExp);
        return pow;
    }
    
    public static vec3i abs(vec3i aVec)
    {
        vec3i abs = aVec.copy();
        abs.abs();
        return abs;
    }
    
    public static vec3i clamp(vec3i aVec, vec3i aBoundsLo, vec3i aBoundsHi)
    {
        vec3i clamp = aVec.copy();
        clamp.clamp(aBoundsLo, aBoundsHi);
        return clamp;
    }
    
    public static vec3i clamp(vec3i aVec, int aBoundsLo, int aBoundsHi)
    {
        vec3i clamp = aVec.copy();
        clamp.clamp(aBoundsLo, aBoundsHi);
        return clamp;
    }
    
    
    
}
